package org.argus.job.worker.cloud.autoconfigure;

import java.util.Arrays;
import java.util.List;

import org.argus.job.common.utils.CommonUtils;
import org.argus.job.worker.cloud.ArgusJobSpringWorker;
import org.argus.job.worker.core.actors.TaskTrackerActor;
import org.argus.job.worker.core.common.PowerJobWorkerConfig;
import org.argus.job.common.network.IServiceInstanceIPParser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Autoconfiguration class for PowerJob-worker.
 *
 * @author songyinyin
 * @since 2020/7/26 16:37
 */
@Configuration
@EnableConfigurationProperties(ArgusJobProperties.class)
@ConditionalOnProperty(prefix = "argusjob.worker", name = "enabled", havingValue = "true", matchIfMissing = true)
public class ArgusJobAutoConfiguration {

    @Value("${server.port:-1}")
    private int port;

    @Bean
    @ConditionalOnMissingBean
    public ArgusJobSpringWorker initPowerJob(ArgusJobProperties properties, IServiceInstanceIPParser workerIPParser) {

        ArgusJobProperties.Worker worker = properties.getWorker();

        /*
         * Address of PowerJob-server node(s). Do not mistake for ActorSystem port. Do not add
         * any prefix, i.e. http://.
         */
        CommonUtils.requireNonNull(worker.getServerAddress(), "serverAddress can't be empty! " +
            "if you don't want to enable powerjob, please config program arguments: powerjob.worker.enabled=false");

        /*
         * Create OhMyConfig object for setting properties.
         */
        PowerJobWorkerConfig config = new PowerJobWorkerConfig();
        /*
         * appName, name of the application. Applications should be registered in advance to prevent
         * error. This property should be the same with what you entered for appName when getting
         * registered.
         */
        config.setAppName(worker.getAppName());
        config.setServerAddress(worker.getServerAddress());
        config.setPort(port);
        config.setProtocol(worker.getProtocol());
        /*
         * For non-Map/MapReduce tasks, {@code memory} is recommended for speeding up calculation.
         * Map/MapReduce tasks may produce batches of subtasks, which could lead to OutOfMemory
         * exception or error, {@code disk} should be applied.
         */
        config.setStoreStrategy(worker.getStoreStrategy());
        /*
         * When enabledTestMode is set as true, PowerJob-worker no longer connects to PowerJob-server
         * or validate appName.
         */
        config.setAllowLazyConnectServer(worker.isAllowLazyConnectServer());
        /*
         * Max length of appended workflow context . Appended workflow context value that is longer than the value will be ignored.
         */
        config.setMaxAppendedWfContextLength(worker.getMaxAppendedWfContextLength());

        config.setTag(worker.getTag());

        config.setMaxHeavyweightTaskNum(worker.getMaxHeavyweightTaskNum());

        config.setMaxLightweightTaskNum(worker.getMaxLightweightTaskNum());

        config.setHealthReportInterval(worker.getHealthReportInterval());
        /*
         * Create ArgusJobSpringWorker object and set properties.
         */
        return new ArgusJobSpringWorker(config, workerIPParser);
    }

    @Bean
    @ConditionalOnMissingBean
    public TaskTrackerActor taskTrackerActor(ArgusJobSpringWorker argusJobSpringWorker) {
        return  new TaskTrackerActor(argusJobSpringWorker.getWorkerRuntime());
    }

}
